package info.niwota.pasta;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

public class NoteListActivity extends ListActivity {
	private static final String LAST_NOTE_ID = "last.note.id";

	// context menu
	private static final int MENU_DELETE = Menu.FIRST + 4;
	private static final int MENU_EDIT = Menu.FIRST + 3;
	private static final int MENU_VIEW = Menu.FIRST + 2;

	private static final String[] PROJECTION = { Note.Notes._ID,
			Note.Notes.TITLE, Note.Notes.BODY, Note.Notes.ATTACHMENT,
			Note.Notes.MODIFIED_DATE };

	private static final int RC_ADD = 2;
	private static final int RC_EDIT = 1;
	private static final int RC_VIEW = 3;

	private static final String TAG = "NoteListActivity";

	private static final long NOTE_ID_NONE = -1;

	public static long getLastId(Context context) {
		try {
			final SharedPreferences p = PreferenceManager
					.getDefaultSharedPreferences(context);
			return p.getLong(LAST_NOTE_ID, NOTE_ID_NONE);
		} catch (Exception e) {
		}
		return NOTE_ID_NONE;
	}

	public static void putLastId(Context context, long id) {
		try {
			final SharedPreferences p = PreferenceManager
					.getDefaultSharedPreferences(context);
			p.edit().putLong(LAST_NOTE_ID, id).commit();
		} catch (Exception e) {
		}
	}

	private SimpleCursorAdapter adapter;

	private MenuItem deleteallMenuItem;

	private MenuItem exportMenuItem;

	private MenuItem importMenuItem;

	private long itemId;
	
	private Cursor mCursor;
	private NoteHelper mHelper;
	private int position = -1;

	private MenuItem clearMenuItem;

	private void checkItem(int pos) {
		ListView v = getListView();
		v.clearChoices();
		v.setItemChecked(pos, true);
	}

	private void doAdd() {
		Intent i = new Intent(this, EditNoteActivity.class);
		//
		startActivityForResult(i, RC_ADD);
	}

	private void doDelete() {
		try {
			final Cursor c = mCursor;
			c.moveToPosition(position);

			final String title = c.getString(c
					.getColumnIndexOrThrow(Note.Notes.TITLE));
			new AlertDialog.Builder(this)
					.setTitle(
							getResources()
									.getString(R.string.title_note_delete))
					.setMessage(title)
					.setPositiveButton(R.string.button_confirm,
							new OnClickListener() {
								public void onClick(DialogInterface dialog,
										int arg1) {
									Uri noteUri = ContentUris.withAppendedId(
											Note.Notes.ALL_NOTES_URI, c
													.getInt(0));
									int del = getContentResolver().delete(
											noteUri, null, null);
									if (del > 0) {
										//
										restoreCheck();
										Toast.makeText(NoteListActivity.this,
												R.string.msg_note_delete,
												Toast.LENGTH_SHORT).show();
									} else {
										Toast
												.makeText(
														NoteListActivity.this,
														getString(
																R.string.msg_note_failed,
																title),
														Toast.LENGTH_SHORT)
												.show();

										// Log.d(TAG, "failed to delete: "
										// + noteUri);
									}
								}
							}).setNegativeButton(R.string.button_cancel, null)
					.show();
		} catch (Exception e) {
			Toast.makeText(this,
					getString(R.string.msg_note_failed, e.getMessage()),
					Toast.LENGTH_SHORT).show();
			// e.printStackTrace();
		}
	}

	private void doDeleteAll() {
		new AlertDialog.Builder(this).setCancelable(true).setTitle(
				getString(R.string.deleteall_confirm_title)).setMessage(
				R.string.text_are_you_sure).setPositiveButton(
				R.string.button_confirm, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface arg0, int arg1) {
						try {
							mHelper.deleteAll();
							updateTitle();
							updatePreference(NOTE_ID_NONE, "", "");
						} catch (Exception e) {
							//
						}
					}
				}).setNegativeButton(R.string.button_cancel, null).create()
				.show();
	}

	private void doEdit() {
		Cursor c = mCursor;
		c.moveToPosition(position);
		//
		String title = c.getString(c.getColumnIndexOrThrow(Note.Notes.TITLE));
		String b = c.getString(c.getColumnIndexOrThrow(Note.Notes.BODY));
		String a = c.getString(c.getColumnIndexOrThrow(Note.Notes.ATTACHMENT));
		//
		Intent i = new Intent(this, EditNoteActivity.class);
		i.putExtra(Note.EXTRA_TITLE, title);
		i.putExtra(Note.EXTRA_BODY, b);
		i.putExtra(Note.EXTRA_ATTACH, a);
		//
		startActivityForResult(i, RC_EDIT);
	}

	private void doExport() {
		try {
			mHelper.doExport();
		} catch (Exception e) {
			e.printStackTrace();
			//
			showError(e);
		}
	}

	private void doImport() {
		try {
			mHelper.doImport();
			restoreCheck();
		} catch (Exception e) {
			e.printStackTrace();
			//
			showError(e);
		}
		
//		new AlertDialog.Builder(this).setCancelable(true).setTitle(
//				getString(R.string.import_confirm_title)).setMessage(
//				R.string.text_are_you_sure).setPositiveButton(
//				R.string.button_confirm, new DialogInterface.OnClickListener() {
//					public void onClick(DialogInterface arg0, int arg1) {
//						
//					}
//				}).setNegativeButton(R.string.button_cancel, null).create()
//				.show();
	}

	private void showError(Exception e) {
		Toast.makeText(this, e.getMessage()+"", Toast.LENGTH_SHORT).show();
	}
	
	private void doPostAdd(Intent data) {
		try {
			String title = data.getStringExtra(Note.EXTRA_TITLE);
			ContentValues values = new ContentValues();
			Long now = System.currentTimeMillis();
			values.put(Note.Notes.TITLE, title);
			values.put(Note.Notes.BODY, getString(data, Note.EXTRA_BODY, ""));
			values.put(Note.Notes.ATTACHMENT, getString(data,
					Note.EXTRA_ATTACH, ""));
			values.put(Note.Notes.CREATED_DATE, now);
			values.put(Note.Notes.MODIFIED_DATE, now);
			//
			Uri noteUri = Uri.withAppendedPath(Note.Notes.ALL_NOTES_URI, title);
			Uri uri = getContentResolver().insert(noteUri, values);
			if (uri != null) {
				// 
				if (Debug.DEBUG) {
					Log.d(TAG, "inserted: " + uri);
				}
				//
				if (Debug.DEBUG) {
					long id = Long.parseLong(uri.getLastPathSegment());
					Log.d(TAG, "rowId:  " + id + " uri: " + uri);
				}
				// 
				Toast.makeText(this, R.string.msg_note_add, Toast.LENGTH_SHORT)
						.show();
				restoreCheck();
			} else {
				// Log.e(TAG, "Failed to insert " + getIntent().getData());
				Toast.makeText(this,
						getString(R.string.msg_note_failed, title),
						Toast.LENGTH_SHORT).show();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void doPostEdit(Intent data) {
		try {
			Cursor c = mCursor;
			c.requery();
			c.moveToPosition(position);
			//
			Uri noteUri = ContentUris.withAppendedId(Note.Notes.ALL_NOTES_URI,
					c.getInt(0));
			ContentValues values = new ContentValues();
			String title = data.getStringExtra(Note.EXTRA_TITLE);
			values.put(Note.Notes.TITLE, title);
			values.put(Note.Notes.BODY, data.getStringExtra(Note.EXTRA_BODY));
			values.put(Note.Notes.MODIFIED_DATE, System.currentTimeMillis());
			getContentResolver().update(noteUri, values,
					"_id = " + c.getInt(0), null);
			//
			restoreCheck();
			Toast.makeText(this, R.string.msg_note_edit, Toast.LENGTH_SHORT)
					.show();
		} catch (Exception e) {
			Toast.makeText(this,
					getString(R.string.msg_note_failed, e.getMessage()),
					Toast.LENGTH_SHORT).show();
			// e.printStackTrace();
		}
	}

	private void doPostView() {
		//
	}

	private void doView() {
		Cursor c = mCursor;
		c.moveToPosition(position);
		//
		String title = c.getString(c.getColumnIndexOrThrow(Note.Notes.TITLE));
		String b = c.getString(c.getColumnIndexOrThrow(Note.Notes.BODY));
		String a = c.getString(c.getColumnIndexOrThrow(Note.Notes.ATTACHMENT));
		//
		Intent i = new Intent(this, ViewNoteActivity.class);
		i.putExtra(Note.EXTRA_TITLE, title);
		i.putExtra(Note.EXTRA_BODY, b);
		i.putExtra(Note.EXTRA_ATTACH, a);
		//
		startActivityForResult(i, RC_VIEW);
	}

	private int findPositionById(long id, int def) {
		try {
			int cnt = adapter.getCount();
			for (int i = 0; i < cnt; i++) {
				long iid = adapter.getItemId(i);
				if (iid == id) {
					return i;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return def;
	}

	private String getString(Intent data, String key, String def) {
		if (data == null) {
			return def;
		}
		String s = data.getStringExtra(key);
		return (s == null ? def : s);
	}

	private void initCheck() {
		long id = getLastId(this);
		//
		Cursor c = mCursor;
		int cnt = c.getCount();
		if (cnt == 0) {
			updateTitle();
			return;
		}
		//
		int pos = findPositionById(id, 0);
		c.moveToPosition(pos);
		checkItem(pos);

		String title = c.getString(c.getColumnIndexOrThrow(Note.Notes.TITLE));
		updateTitle(title, cnt);
		itemId = c.getLong(c.getColumnIndexOrThrow(Note.Notes._ID));
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			case RC_EDIT:
				doPostEdit(data);
				break;
			case RC_ADD:
				doPostAdd(data);
				break;
			case RC_VIEW:
				doPostView();
				break;
			default:
			}
		}
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterView.AdapterContextMenuInfo mi = (AdapterView.AdapterContextMenuInfo) item
				.getMenuInfo();
		if (mi == null) {
			return true;
		}
		position = mi.position;
		//
		switch (item.getItemId()) {
		case MENU_VIEW:
			doView();
			break;
		case MENU_EDIT:
			doEdit();
			break;
		case MENU_DELETE:
			doDelete();
			break;
		default:
		}
		return true;
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		requestWindowFeature(Window.FEATURE_LEFT_ICON);
		
		setContentView(R.layout.notes);

		Intent intent = getIntent();
		Uri uri = null;
		String query = null;
		//
		if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
			query = intent.getStringExtra(SearchManager.QUERY);
		} else if (savedInstanceState != null) {
			query = savedInstanceState.getString(SearchManager.QUERY);
		}
		if (query != null && query.length() > 0) {
			uri = Uri
					.withAppendedPath(Note.Notes.SEARCH_URI, Uri.encode(query));
		}
		if (uri == null) {
			// default (all notes)
			uri = Note.Notes.ALL_NOTES_URI;
		}

		// Do the query
		mCursor = managedQuery(uri, PROJECTION, null, null,
				Note.Notes.DEFAULT_SORT_ORDER);

		mHelper = new NoteHelper(this);
		//
		adapter = new SimpleCursorAdapter(this,
				R.layout.notes_item, mCursor,
				new String[] { Note.Notes.TITLE },
				new int[] { android.R.id.text1 });

		final ListView lv = getListView();
		lv.setAdapter(adapter);
		lv.setItemsCanFocus(false);
		lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
		lv.clearChoices();
		//
		int cnt = mCursor.getCount();
		//
		if (Debug.DEBUG) {
			Log.d(TAG, "total entries: " + cnt);
		}
		//
		if (cnt <= 0) {
			//
			if (Debug.DEBUG) {
				Log.d(TAG, "populating default entries");
			}
			//
			mHelper.doLoad();
			mCursor.requery();
		}
		//
		registerForContextMenu(lv);
		//
		getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
				R.drawable.icon);
		//
		initCheck();
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		menu.add(0, MENU_VIEW, 0, R.string.menu_view);
		menu.add(0, MENU_EDIT, 0, R.string.menu_edit);
		menu.add(0, MENU_DELETE, 0, R.string.menu_delete);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.notes_options, menu);
		//add
		//quit
		//
		//conditional
		clearMenuItem = menu.findItem(R.id.notes_clear_opt_menu_id);
		//
		deleteallMenuItem = menu.findItem(R.id.notes_deleteall_opt_menu_id);
		//
		exportMenuItem = menu.findItem(R.id.notes_export_opt_menu_id);
		importMenuItem = menu.findItem(R.id.notes_import_opt_menu_id);
		//
		//TODO hide for now
		//exportMenuItem.setVisible(false);
		//importMenuItem.setVisible(false);
		//
		return true;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			//cancel only
			//Utils.addNotification(this);
			finish();
			return true;
		} else {
			return super.onKeyDown(keyCode, event);
		}
	}

	private void doHibernate() {
		//save, copy selection. 
		//add self to status bar
		saveSelection();
		//Utils.addNotification(this);
		finish();
	}

	private void saveSelection() {
		try {
			Cursor c = mCursor;
			long id = NOTE_ID_NONE;
			String title = "";
			String body = "";
			String attach = "";
			int pos = findPositionById(itemId, -1);
			if (pos != -1) {
				c.moveToPosition(pos);
				id = c.getLong(c.getColumnIndexOrThrow(Note.Notes._ID));
				title = c.getString(c.getColumnIndexOrThrow(Note.Notes.TITLE));
				body = c.getString(c.getColumnIndexOrThrow(Note.Notes.BODY));
				attach = c.getString(c
						.getColumnIndexOrThrow(Note.Notes.ATTACHMENT));
			}
			updatePreference(id, title, body);
			//
			Intent data = new Intent();
			data.putExtra(Note.EXTRA_TITLE, title);
			data.putExtra(Note.EXTRA_BODY, body);
			data.putExtra(Note.EXTRA_ATTACH, attach);
			setResult(RESULT_OK, data);
			//
			cookPasta(title, body);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void cookPasta(String title, String body) {
		// copy content to clipboard so other applications can use
		String content = (TextUtils.isEmpty(body) ? title : body);
		Utils.copyToClipboard(this, content);
		//
		Toast.makeText(NoteListActivity.this,
				R.string.msg_note_copied_to_clipboard,
				Toast.LENGTH_SHORT).show();
	}

	private void doQuit() {
		//Utils.removeNotification(this);
		finish();
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		savePreference();
		//
		super.onSaveInstanceState(outState);
	}

	private void savePreference() {
		try {
			Cursor c = mCursor;
			long id = NOTE_ID_NONE;
			String title = "";
			String body = "";
			int pos = findPositionById(itemId, -1);
			if (pos != -1) {
				c.moveToPosition(pos);
				id = c.getLong(c.getColumnIndexOrThrow(Note.Notes._ID));
				title = c.getString(c.getColumnIndexOrThrow(Note.Notes.TITLE));
				body = c.getString(c.getColumnIndexOrThrow(Note.Notes.BODY));
			}
			updatePreference(id, title, body);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	protected void onListItemClick(ListView list, View view, int pos, long id) {
		Cursor c = mCursor;
		c.moveToPosition(pos);
		itemId = c.getLong(c.getColumnIndexOrThrow(Note.Notes._ID));
		String title = c.getString(c.getColumnIndexOrThrow(Note.Notes.TITLE));
		updateTitle(title, c.getCount());
		//
		doHibernate();
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.notes_add_opt_menu_id:
			doAdd();
			return true;
		case R.id.notes_clear_opt_menu_id:
			doClear();
			return true;
		case R.id.notes_export_opt_menu_id:
			doExport();
			return true;
		case R.id.notes_import_opt_menu_id:
			doImport();
			return true;
		case R.id.notes_deleteall_opt_menu_id:
			doDeleteAll();
			return true;
		case R.id.notes_quit_opt_menu_id:
			doQuit();
			return true;
		default:
			return false;
		}
	}

	private void doClear() {
		//clear clipboard
		Utils.copyToClipboard(this, "");
		Toast.makeText(NoteListActivity.this,
				R.string.msg_note_cleared_clipboard,
				Toast.LENGTH_SHORT).show();
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		importMenuItem.setEnabled(true);
		//
		boolean has = (mCursor.getCount() > 0);
		deleteallMenuItem.setEnabled(has);
		exportMenuItem.setEnabled(has);
		//
		clearMenuItem.setEnabled(Utils.hasClipboardText(this));
		//
		return true;
	}

	private void restoreCheck() {
		// restore the original checked item after destructive updates
		Cursor c = mCursor;
		c.requery();
		int cnt = c.getCount();
		if (cnt == 0) {
			updateTitle();
			itemId = NOTE_ID_NONE;
			updatePreference(NOTE_ID_NONE, "", "");
			return;
		}
		int pos = findPositionById(itemId, 0);
		// preference updated when BACK
		//
		checkItem(pos);
		c.moveToPosition(pos);
		String t = c.getString(c.getColumnIndexOrThrow(Note.Notes.TITLE));
		updateTitle(t, cnt);
		itemId = c.getLong(c.getColumnIndexOrThrow(Note.Notes._ID));
	}

	private void updatePreference(long id, String title, String body) {
		putLastId(this, id);
		Preferences.putNoteTitle(this, title);
		Preferences.putNoteBody(this, body);
	}

	private void updateTitle() {
		setTitle(R.string.title_notes_none);
	}

	private void updateTitle(String title, int cnt) {
		if (cnt == 0) {
			setTitle(R.string.title_notes_none);
			return;
		}
		String t = getString(R.string.title_notes_count, cnt);
		setTitle(t);
	}
}
